package api

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"sync"
	"time"

	"github.com/gorilla/websocket"
)

// 用户websocket连接映射
var (
	OnlineUser     = make(map[uint]*websocket.Conn)
	onlineUserLock sync.RWMutex
)

// 通知消息结构
type Notification struct {
	Type       string      `json:"type"`         // 通知类型：follow、unfollow、like、comment等
	FromUserID uint        `json:"from_user_id"` // 触发通知的用户ID
	ToUserID   uint        `json:"to_user_id"`   // 接收通知的用户ID
	Content    string      `json:"content"`      // 通知内容
	Timestamp  int64       `json:"timestamp"`    // 时间戳
	Extra      interface{} `json:"extra"`        // 扩展数据
}

// WebSocket响应结构
type WSResp struct {
	Code uint        `json:"code"` // 状态码
	Msg  string      `json:"msg"`  // 消息说明
	Data interface{} `json:"data"` // 响应数据
}

// 发送关注通知
func SendFollowNotification(fromUserID, toUserID uint, isFollow bool) error {
	var notification *Notification

	if isFollow {
		notification = &Notification{
			Type:       "follow",
			FromUserID: fromUserID,
			ToUserID:   toUserID,
			Content:    fmt.Sprintf("用户：%d 关注了你", fromUserID),
			Timestamp:  time.Now().Unix(),
			Extra: map[string]interface{}{
				"follow_time": time.Now().Unix(),
			},
		}
	} else {
		notification = &Notification{
			Type:       "unfollow",
			FromUserID: fromUserID,
			ToUserID:   toUserID,
			Content:    fmt.Sprintf("用户：%d 取消关注了你", fromUserID),
			Timestamp:  time.Now().Unix(),
			Extra:      nil,
		}
	}

	return SendNotificationToUser(toUserID, notification)
}

// 发送通知给指定用户
func SendNotificationToUser(targetUserID uint, notification *Notification) error {
	log.Printf("尝试发送通知给用户 %d", targetUserID)

	// 获取当前在线用户状态（用于调试）
	onlineUserLock.RLock()
	currentOnlineCount := len(OnlineUser)
	onlineUserIDs := getOnlineUserIDs()
	onlineUserLock.RUnlock()

	log.Printf("当前在线用户数: %d, 在线用户ID: %v", currentOnlineCount, onlineUserIDs)

	// 加读锁保护OnlineUser的读取
	onlineUserLock.RLock()
	userConn, exists := OnlineUser[targetUserID]
	onlineUserLock.RUnlock()

	if !exists {
		log.Printf("用户 %d 不在线，当前在线用户: %v", targetUserID, onlineUserIDs)
		return fmt.Errorf("用户 %d 不在线", targetUserID)
	}

	// 检查连接是否真的有效
	if userConn == nil {
		log.Printf("用户 %d 的连接为nil，清理无效连接", targetUserID)
		onlineUserLock.Lock()
		delete(OnlineUser, targetUserID)
		onlineUserLock.Unlock()
		return fmt.Errorf("用户 %d 的连接无效", targetUserID)
	}

	log.Printf("找到用户 %d 的WebSocket连接，准备发送通知", targetUserID)

	// 构建通知响应
	response := WSResp{
		Code: http.StatusOK,
		Msg:  "新通知",
		Data: map[string]interface{}{
			"cmd":          "notification",
			"notification": notification,
		},
	}

	responseStr, err := json.Marshal(response)
	if err != nil {
		log.Printf("序列化通知失败: %v", err)
		return fmt.Errorf("序列化通知失败: %v", err)
	}

	// 设置写超时，避免阻塞
	userConn.SetWriteDeadline(time.Now().Add(5 * time.Second))
	if err := userConn.WriteMessage(websocket.TextMessage, responseStr); err != nil {
		log.Printf("WebSocket写入失败: %v", err)
		// 如果发送失败，从在线列表中移除
		onlineUserLock.Lock()
		delete(OnlineUser, targetUserID)
		onlineUserLock.Unlock()
		log.Printf("已清理用户 %d 的无效连接", targetUserID)
		return fmt.Errorf("发送通知失败: %v", err)
	}

	log.Printf("通知已成功发送给用户 %d: %s", targetUserID, notification.Content)
	return nil
}

// 获取当前在线用户ID列表（用于调试）
func getOnlineUserIDs() []uint {
	ids := make([]uint, 0, len(OnlineUser))
	for id := range OnlineUser {
		ids = append(ids, id)
	}
	return ids
}

// 添加用户到在线列表（在WebSocket连接建立时调用）
func AddOnlineUser(userID uint, conn *websocket.Conn) {
	onlineUserLock.Lock()
	defer onlineUserLock.Unlock()

	// 如果用户已在线，关闭旧连接
	if oldConn, exists := OnlineUser[userID]; exists {
		oldConn.Close()
		log.Printf("关闭用户 %d 的旧连接", userID)
	}

	OnlineUser[userID] = conn
	log.Printf("用户 %d 已添加到在线列表，当前在线用户数: %d", userID, len(OnlineUser))
}

// 从在线列表移除用户（在WebSocket连接断开时调用）
func RemoveOnlineUser(userID uint) {
	onlineUserLock.Lock()
	defer onlineUserLock.Unlock()

	if conn, exists := OnlineUser[userID]; exists {
		conn.Close()
		delete(OnlineUser, userID)
		log.Printf("用户 %d 已从在线列表移除，当前在线用户数: %d", userID, len(OnlineUser))
	}
}
